package cn.zyl.demo.common.crypto;

import cn.zyl.demo.common.constant.CommonConstant;
import cn.zyl.demo.common.enums.CharsetEnum;
import cn.zyl.demo.common.enums.MsgEnum;
import cn.zyl.demo.common.exception.CryptoHandlerException;
import cn.zyl.demo.common.permanent.MsgProperties;
import cn.zyl.demo.common.tools.HexTool;
import cn.zyl.demo.common.tools.StringTool;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;

/**
 * TripleDesCryptoHandler类说明:3DES加密方式将字符串加密，并将结果转化为16进制表示的字符串
 *
 * @author wsz
 * @version v1.0
 * @date 2020-07-22
 */
public class TripleDesCryptoHandler extends AbstractCryptoHandler{
    private static final String ALGORITHM = "DESede";
    /**
     * 加密方法
     *
     * @param input     输入字符
     * @param secretKey 秘钥
     * @return 密文
     * @throws CryptoHandlerException 加解密处理异常
     */
    @Override
    protected String encrypt(String input, String secretKey) throws CryptoHandlerException {
        try {
            if(StringTool.isEmpty(input)){ return input; }
            //生成密钥
            SecretKey desKey = new SecretKeySpec(build3DesKey(secretKey), ALGORITHM);
            //实例化负责加密/解密的Cipher工具类
            Cipher c1 = Cipher.getInstance(ALGORITHM);
            //初始化为加密模式
            c1.init(Cipher.ENCRYPT_MODE, desKey);
            return HexTool.byteArr2HexStr(c1.doFinal(input.getBytes()));
        } catch (Exception e) {
            throw new CryptoHandlerException(MsgProperties.get(MsgEnum.ERROR_CRYPTO_FAIL_ENCRYPT),e);
        }
    }

    /**
     * 解密方法
     *
     * @param input     密文
     * @param secretKey 秘钥
     * @return 明文
     * @throws CryptoHandlerException 加解密处理异常
     */
    @Override
    protected String decrypt(String input, String secretKey) throws CryptoHandlerException {
        try {
            if(StringTool.isEmpty(input)){ return input; }
            SecretKey desKey = new SecretKeySpec(build3DesKey(secretKey), ALGORITHM);
            Cipher c1 = Cipher.getInstance(ALGORITHM);
            //初始化为解密模式
            c1.init(Cipher.DECRYPT_MODE, desKey);
            return new String (c1.doFinal(HexTool.hexStr2ByteArr(input)));
        } catch (Exception e) {
            throw new CryptoHandlerException(MsgProperties.get(MsgEnum.ERROR_CRYPTO_FAIL_DECRYPT),e);
        }
    }

    /**
     * 根据字符串生成密钥字节数组
     * @param keyStr 密钥字符串
     * @return 字节数组
     * @throws UnsupportedEncodingException 不支持的字符编码
     */
    public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
        //声明一个24位的字节数组，默认里面都是0
        byte[] key = new byte[24];
        //将字符串转成字节数组
        byte[] temp = keyStr.getBytes(CharsetEnum.UTF_8.getType());
        /* 执行数组拷贝 System.arrayCopy(源数组，从源数组哪里开始拷贝，目标数组，拷贝多少位) */
        //如果temp不够24位，则拷贝temp数组整个长度的内容到key数组中
        //如果temp大于24位，则拷贝temp数组24个长度的内容到key数组中
        System.arraycopy(temp, 0, key, 0, Math.min(key.length, temp.length));
        return key;
    }
    public static void main(String[] args) {
        AbstractCryptoHandler cryptoHandler = new TripleDesCryptoHandler();
        System.out.println(cryptoHandler.encrypt("15479532321", CommonConstant.CRYPTO_SECRET_KEY_TEST));
        System.out.println(cryptoHandler.encrypt("12345789497",CommonConstant.CRYPTO_SECRET_KEY_TEST));
        System.out.println(cryptoHandler.decrypt("4591942d4c18491dad96487ef24f0a97",CommonConstant.CRYPTO_SECRET_KEY_TEST));
        System.out.println(cryptoHandler.decrypt("19062076910f3de3b8c1d52a1d9c3c71",CommonConstant.CRYPTO_SECRET_KEY_TEST));
    }
}
